Chaerin.dev

[JS] Optional Chaining ํ™œ์šฉ

๋ฌธ์ œ์ƒํ™ฉ๐Ÿคฏ

๋‚ด๊ฐ€ ๋งŒ๋“ค๋ ค๋Š” ํ™”๋ฉด์€ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด input ์ฐฝ์— ์ƒˆ ๋””๋ ‰ํ† ๋ฆฌ๋ช…์„ ์ž…๋ ฅํ•˜๊ณ  ์ €์žฅ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์นด๋“œ ์œ„์— ๋– ์žˆ๋Š” ํ™”๋ฉด์ด ์‚ฌ๋ผ์ง€๊ณ  ์ €์žฅํ™”๋ฉด์ด ๋‚˜์˜ค๋Š” ๊ฒƒ์ด์˜€๋‹ค. ํ•˜์ง€๋งŒ ์ €์žฅ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ณ  ์นด๋“œ ์œ„์— ๋– ์žˆ๋Š” ํ™”๋ฉด์€ ์‚ฌ๋ผ์กŒ์ง€๋งŒ ์ €์žฅํ™”๋ฉด์ด ๋‚˜์˜ค์งˆ ์•Š์•˜๋‹ค. ๊ทธ ์ด์œ ๋Š” ๋ฐ”๋กœ input์ฐฝ์— focus๊ฐ€ ๊บผ์ง€๋ฉด ์นด๋“œ ์œ„์— ๋– ์žˆ๋Š” ํ™”๋ฉด์ด ์‚ฌ๋ผ์ง€๋„๋ก ๋งŒ๋“ค์–ด๋†จ๋Š”๋ฐ ๊ทธ ์ด๋ฒคํŠธ๊ฐ€ ์ €์žฅ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์‹คํ–‰๋˜๋Š” ์ด๋ฒคํŠธ๋ณด๋‹ค ๋จผ์ € ์ผ์–ด๋‚˜์„œ ์ €์žฅ์ด ์ผ์–ด๋‚˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ํ™”๋ฉด์ด ๊บผ์ ธ๋ฒ„๋ฆฐ ๊ฒƒ์ด์˜€๋‹ค.

๊ทธ๋ž˜์„œ ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ–ˆ๋‹ค.

<ButtonWrap isShow={isShow} inputChange={inputChange}>
  <input
    className="addInput"
    placeholder="์ƒˆ ๋””๋ ‰ํ† ๋ฆฌ ๋ช…์„ ์ž…๋ ฅํ•˜์„ธ์š”"
    onChange={e => {
      inputText.onChange(e)
      setInputChange(true)
    }}
    onFocus={e => {
      e.stopPropagation()
      setCardHoverInputState(true)
    }}
    onBlurCapture={e => {
      e.stopPropagation()
      console.log(e.relatedTarget.className)
      if (e.relatedTarget.className !== 'addBtn') {
        setCardHoverInputState(false)
      }
    }}
    value={inputText.value}
    maxLength={20}
    onKeyPress={onKeyPress}
  />
  <button className="addBtn" onClick={addDirHandler}>
    ์ €์žฅ
  </button>
</ButtonWrap>

ํด๋ฆญ ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚œ ์ปดํฌ๋„ŒํŠธ์˜ className์ด โ€œaddBtnโ€์ด ์•„๋‹ ๋•Œ ์ €์žฅ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฌ์ง€ ์•Š์•˜์„ ๋•Œ๋งŒ ์นด๋“œ ์œ„์— ๋– ์žˆ๋Š” ํ™”๋ฉด์„ ์‚ฌ๋ผ์ง€๋„๋ก ๊ตฌ์„ฑํ•œ ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ์‹คํ–‰์‹œํ‚ค์ž ์—๋Ÿฌ๊ฐ€ ๋‚ฌ๋‹คโ€ฆ๐Ÿ˜‚ ๊ทธ ์ด์œ ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํด๋ฆญํ•œ ๊ณณ์ด null๋กœ ์ฐํžˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. null์˜ ํด๋ž˜์Šค ์ด๋ฆ„์€ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— error๊ฐ€ ๋‚œ ๊ฒƒ์ด๋‹ค.

์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ• ๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ์˜ต์…”๋„ ์ฒด์ด๋‹์ด ๋– ์˜ฌ๋ž๋‹ค.

๋ฌธ์ œํ•ด๊ฒฐ๐Ÿค—

?.์€ ?.โ€™์•žโ€™์˜ ํ‰๊ฐ€ ๋Œ€์ƒ์ด undefined๋‚˜ null์ด๋ฉด ํ‰๊ฐ€๋ฅผ ๋ฉˆ์ถ”๊ณ  undefined๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ €๋ฒˆ ์˜ต์…”๋„ ์ฒด์ด๋‹ ํฌ์ŠคํŒ…์—์„œ ๊ฐ€์ ธ์˜จ ๋ฌธ์žฅ์ด๋‹ค. ์˜ต์…”๋„์ฒด์ด๋‹์—์„œ ?.์•ž์˜ ํ‰๊ฐ€๋Œ€์ƒ์ด null์ด๋ฉด undefined๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์ง€ ์•Š๋Š”๋‹ค.

e.relatedTarget.className์„ e?.relatedTarget?.className๋กœ ์ˆ˜์ •ํ•ด์ฃผ๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ณณ์ด null๋กœ ์ฐํ˜€๋„ className์„ ๋ถˆ๋Ÿฌ์˜ค์ง€ ์•Š๊ณ  undefined๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ฅ˜๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋ฅผ ์ ์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด๋ณด์•˜๋‹ค.

<ButtonWrap isShow={isShow} inputChange={inputChange}>
  <input
    className="addInput"
    placeholder="์ƒˆ ๋””๋ ‰ํ† ๋ฆฌ ๋ช…์„ ์ž…๋ ฅํ•˜์„ธ์š”"
    onChange={e => {
      inputText.onChange(e)
      setInputChange(true)
    }}
    onFocus={e => {
      e.stopPropagation()
      setCardHoverInputState(true)
    }}
    onBlurCapture={e => {
      e.stopPropagation()
      console.log(e?.relatedTarget?.className)
      if (e?.relatedTarget?.className !== 'addBtn') {
        setCardHoverInputState(false)
      }
    }}
    value={inputText.value}
    maxLength={20}
    onKeyPress={onKeyPress}
  />
  <button className="addBtn" onClick={addDirHandler}>
    ์ €์žฅ
  </button>
</ButtonWrap>

console ์ถœ๋ ฅ๊ฒฐ๊ณผ

์˜ต์…”๋„ ์ฒด์ด๋‹์˜ ๊ฒฐ๊ณผ๋กœ undefined๋ฅผ ๋ฐ˜ํ™˜ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค!

๋Š๋‚€์ 

์‚ฌ์‹ค ์˜ต์…”๋„์ฒด์ด๋‹ ํฌ์ŠคํŒ…์„ ํ•˜๋ฉด์„œ ์„œ๋ฒ„์—์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ ์ด์™ธ์— ๋‹ค๋ฅธ ์˜ˆ์‹œ๋Š” ์ฐพ์•„๋ณด๊ธฐ ํž˜๋“ค์–ด์„œ ํ™œ์šฉ์„ ๊ฑฐ์˜ ๋ชปํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ์ด๋Ÿฐ ์‹์œผ๋กœ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐœ๋…์ด๋ผ๋Š” ๊ฑธ ๋Š๊ผˆ๋‹ค.

์˜ต์…”๋„ ์ฒด์ด๋‹์„ ๋ชฐ๋ž๋‹ค๋ฉด ? :๋‚˜ && if{...}else{...}๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ–ˆ์„ํ…๋ฐ ๊ทธ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•œ ?.์œผ๋กœ ํ•ด๊ฒฐํ•ด์„œ ์ฝ”๋“œ๊ฐ€ ๋” ๊น”๋”ํ•ด์ง„ ๊ฒƒ ๊ฐ™๋‹ค!


Written by@Chaerin
Tech Blog๐Ÿ“•

GitHubLinkedIn